import abc
import csv
from datetime import date, timedelta, datetime
import difflib
import os.path
import json
import sys
import urllib, urllib2
import urlparse

DATA_DIR = "data"
TEAMS_CSV = "teams.csv"

BASE_URL = "http://api.fanfeedr.com/basic/v1/"


class APIQuery(object):
  API_KEY = "6uswbggs25fgzt969bv4s8b6"
  FORMAT = "json"

  def __init__(self, action, **query_params):
    self.query_params = dict(appId=self.API_KEY, format=self.FORMAT)
    self.query_params.update(query_params)
    self.action = action
    
  def get(self):
    url = urlparse.urljoin(BASE_URL, self.action)
    data = urllib.urlencode(self.query_params)
    try:
      opener = urllib2.urlopen(url, data)
      response_json = opener.read()
      return json.loads(response_json)
    except (urllib2.URLError, urllib2.HTTPError) as e:
      print "Whoops! Something went wrong: %r" % e
      raise e


class Game(object):
  def __init__(self, game_data):
    self.game_data = game_data

  def results_available(self):
    return self.game_data["status"] == "FINAL" or self.game_data["is_in_progress"]

  def __repr__(self):
    return "Game(%r)" % self.game_data

  def __str__(self):
    return "%s @ %s, %s" % (self.away_team(), self.home_team(), self.gametime())

  def home_team(self):
    return self.game_data["home"]["team"]["title"]

  def away_team(self):
    return self.game_data["away"]["team"]["title"]

  def total_score(self):
    return int(self.game_data["away"]["score"]) + int(self.game_data["home"]["score"])

  def gametime(self):
    date_data = self.game_data["date"]
    gametime = datetime(year=date_data["year"],
                        month=date_data["month"],
                        day=date_data["day"],
                        hour=date_data["hour"])
    return gametime


class GameOracle(object):
  __metaclass__ = abc.ABCMeta
  
  @abc.abstractmethod
  def __init__(self, game):
    pass

  @abc.abstractmethod
  def __str__(self):
    pass

  @abc.abstractmethod
  def ask(self):
    pass


class TotalScoreOracle(GameOracle):

  def __init__(self, game):
    self.game = game

  def __str__(self):
    return "Total Score Over/Under"

  def ask(self):
    try:
      g = int(raw_input("Over/under for total score of this game: "))
      if g < 0:
        raise ValueError("Non-negative number required!")
      if self.game.total_score() >= g:
        print "Yes! The total score is at least %s." % g
      else:
        print "Nope! The total score is less than %s." % g
    except ValueError:
      print "Supply a non-negative value fuckface."

def load_teams():
  fname = os.path.join(DATA_DIR, TEAMS_CSV)
  reader = csv.reader(open(fname, "U"))
  return dict([(team_name, full_resource) for team_name, full_resource, _ in reader])
    
def fetch_games(team_resource):
  start = date.today() - timedelta(days=7)
  q = APIQuery(action="schedule", start_date=start.isoformat(), resource=team_resource)
  games = q.get()
  return [Game(g_data) for g_data in games]

def user_choice(category_name, options):
  chosen = None
  while not chosen:
    try:
      for i, option in enumerate(options):
        print "[%s] %s" % (i, option)
      c = int(raw_input("Please pick a %s (default %s): " % (category_name, options[0])) or "0")
      chosen = options[c]
    except (ValueError, IndexError):
      print "Not a valid choice asshole!"
  return chosen

def main(args):
  sys.stdout.write("Loading team information...")
  teams = load_teams()
  sys.stdout.write(" done.\n")
  while True:
    name = raw_input("Please enter a team name: ")
    matches = difflib.get_close_matches(name, teams.keys())
    if not matches:
      continue
    team = user_choice("team", matches)
    games = fetch_games(teams[team])
    recent_games = sorted([g for g in games if g.results_available()],
                          key=lambda g: g.gametime(),
                          reverse=True)
    game = user_choice("game", recent_games)
    while True:
      oracles = [TotalScoreOracle(game)]
      oracle = user_choice("question", oracles)
      oracle.ask()

if __name__ == "__main__":
  main(sys.argv[1:])

